package com.pop.hive;

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * 一进多出
 * 函数
 *
 * 实现explorer功能，输出字符串，以，隔开
 * hello,spark,hadoop
 * 输出
 * hello
 * spark
 * hadoop
 */
public class MyUDTF extends GenericUDTF {

    // 输出数据的集合
    private ArrayList<String> outputList = new ArrayList<>();

    @Override
    public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {

        /**
         * 字段名，有的时候，你炸裂出来的数据，会出现一些
         * 奇怪的字段名，例如 c_0 a_0 这样
         * 这个列表可以帮你自定义希望展示出来的名字
         */
        List<String> fieldNames = new ArrayList<>();
        fieldNames.add("word");
        /**
         * 输出数据的类型
         */
        List<ObjectInspector> objectInspectors = new ArrayList<>();
        objectInspectors.add(
                PrimitiveObjectInspectorFactory
                        .javaStringObjectInspector
        );

        // 由于炸裂出来的字段可能会含有多个行，多个列
        // 多个行则意味着字段名不止一个，所以fieldNames是数组
        // 而输出的类型也是一样的，explor可以炸裂数组和map所以
        // 结果看起来也是多行多列的。

        return ObjectInspectorFactory
                .getStandardStructObjectInspector(
                        fieldNames,objectInspectors );
    }

    /**
     * 处理数据
     * @param objects
     * @throws HiveException
     */
    @Override
    public void process(Object[] objects) throws HiveException {
        // 处理数据 hello,spark,hadoop
        // 取出输入数据
        String input = objects[0].toString();
        //按照逗号分隔
        String[] words = input.split(",");

        // 3.遍历数据写出
        for (String word:words){
            //清空集合,保证每次都会输出一个，不然输出总会累加
            /*
            * 但是需要额外申明的是，因为你只要输出一个字符串，所以
            * 你这里清空了，限制一个，如果你希望输出更多
            * 这个地方就不能这样写了，所以要视场景而定。
            * */
            outputList.clear();

            //将数据放入集合
            outputList.add(word);

            //输出语句
            forward(outputList);
        }
        // 写到缓冲区，也是一个输出语句

    }

    /**
     * 收尾
     * @throws HiveException
     */
    @Override
    public void close() throws HiveException {

    }
}
